package com.sugar.base.core;

import java.io.Serializable;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.LinkedHashMap;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.springframework.orm.hibernate3.HibernateCallback;

import com.sugar.base.exception.SystemException;
import com.sugar.base.query.BaseQuery;
import com.sugar.base.query.PageModel;

/**
 * @标题：实现IBaseDao
 * @描述：DAO层的具体化操作
 * @编写者：杨浩泉
 * @日期：2011-5-8 <b>下午04:47:13</b>
 */
@SuppressWarnings("unchecked")
public class IHibernateBaseDaoSupport<T> extends HibernateTemplateSupport implements IHibernateBaseDao<T> {

	private final Log log = LogFactory.getLog(getClass()) ;

	@Override
	public void deleteEntityBaseDao(T entity) throws RuntimeException {
		this.getHibernateTemplate().delete(entity) ;
		this.log.info("[....CoreDAO]：执行了删除操作") ;
	}

	@Override
	public void deleteEntityByIdBaseDao(Class<T> entityName, Serializable delId)
			throws RuntimeException {
		this.getHibernateTemplate().delete(this.getEntityById(entityName, delId)) ;
		this.log.info("[....CoreDAO]：执行了根据ID进行删除操作") ;
	}

	@Override
	public void deleteEntityMoreIdBaseDao(final Class<T> entityName, final Object[] delIds)
			throws RuntimeException {
		
		this.getHibernateTemplate().execute(new HibernateCallback() {
			@Override
			public Object doInHibernate(Session session) throws HibernateException,
					SQLException {
				
				if(null != delIds && delIds.length > 0) {
					
					for(int i=0; i<delIds.length; i++) {
						session.delete(getEntityById(entityName, delIds[i].toString())) ;
						if(i%20==0) {
							session.flush() ;
							session.clear() ;
						}
					}
				}
				return null;
			}
		}) ;
	}

	@Override
	public int executeUpdateOrDeleteByField(final String queryString, final String field,
			String whereString, final Object[] param) throws RuntimeException {
		
		this.getHibernateTemplate().execute(new HibernateCallback() {
			@Override
			public Object doInHibernate(Session session) throws HibernateException,
					SQLException {
				
				Query query = session.createQuery(queryString + buildWhereString(field));
				setQueryParameter(query, param) ;
				
				return query.executeUpdate() ;
			}
		}) ;
		return 0;
	}

	@Override
	public T findEntityByParam(final String queryString, final String whereString,
			final Object[] param) throws RuntimeException {
		
		return (T) this.getHibernateTemplate().execute(new HibernateCallback() {
			@Override
			public Object doInHibernate(Session session) throws HibernateException,
					SQLException {
				
				Query query = session.createQuery(queryString + buildWhereString(whereString)) ;
				setQueryParameter(query,param) ;
				
				return query.uniqueResult() ;
			}
		}) ;
	}

	@Override
	public List<T> findMoreEntityByParam(final String queryString, final String whereString,
			final Object[] param, final LinkedHashMap<String, String> orderby)
			throws RuntimeException {
		return  (List<T>) this.getHibernateTemplate().execute(new HibernateCallback() {
			
			@Override
			public Object doInHibernate(Session session) throws HibernateException,
					SQLException {
				
				Query query = session.createQuery(queryString + buildWhereString(whereString) + buildOrderByString(orderby)) ;
				setQueryParameter(query, param) ;
				
				return query.list() ;
			}
		}) ;
	}

	@Override
	public List<T> findMoreEntityByParam(String queryString, String whereString,
			Object[] param) throws RuntimeException {
		return this.findMoreEntityByParam(queryString, whereString, param, null);
	}

	@Override
	public List<T> findMoreEntityByParam(String queryString,
			LinkedHashMap<String, String> orderby) throws RuntimeException {
		return this.findMoreEntityByParam(queryString, null, null, orderby) ;
	}

	@Override
	public List<T> findMoreEntityByParam(String queryString) throws RuntimeException {
		return this.findMoreEntityByParam(queryString, null, null, null) ;
	}

	@Override
	public T getEntityById(Class<T> entityName, Serializable id)
			throws RuntimeException {
		return (T) this.getHibernateTemplate().get(entityName, id);
	}

	
	@Override
	public PageModel<T> getScrollRecord(final String queryString, final String whereString,
			final Object[] param, final int firstPage, final int pageSize,
			final LinkedHashMap<String, String> orderby) throws RuntimeException {
		
		return (PageModel<T>) this.getHibernateTemplate().execute(new HibernateCallback() {
			@Override
			public Object doInHibernate(Session session) throws HibernateException,
					SQLException {
				PageModel<T> pm = null ; 
				List<T> record = null ;
				System.out.println(queryString + buildWhereString(whereString) + buildOrderByString(orderby));
				
				Query query = session.createQuery(queryString + buildWhereString(whereString) + buildOrderByString(orderby)) ; ;
				query.setFirstResult(firstPage) ;
				query.setMaxResults(pageSize) ;
 				setQueryParameter(query, param) ;
				
				
				record = query.list() ;
				
				if(null != record && record.size() > 0) {
					pm = new PageModel<T>() ;
					pm.setRecord(record) ;
					pm.setTotal(((Long)getRecordTotal(session, queryString, whereString, param)).intValue()) ;
				}
				
				log.info("[][][][][]][][[[[[[[[[[[[[[[[[[[[[[分页查询]]]]]]]]]]]]]]]]]]]]]]]]") ;
				return pm;
			}
		}) ;
	}

	@Override
	public PageModel<T> getScrollRecord(String queryString, String whereString,
			Object[] param, int firstPage, int pageSize)
			throws RuntimeException {
		
		return this.getScrollRecord(queryString, whereString, param, firstPage, pageSize, null) ;
	}

	@Override
	public PageModel<T> getScrollRecord(String queryString, int firstPage,
			int pageSize, LinkedHashMap<String, String> orderby)
			throws RuntimeException {
		
		return this.getScrollRecord(queryString, null, null, firstPage, pageSize, orderby);
	}

	@Override
	public PageModel<T> getScrollRecord(String queryString, int firstPage,
			int pageSize) throws RuntimeException {
		return this.getScrollRecord(queryString, null, null, firstPage, pageSize, null);
	}

	@Override
	public T loadEntityById(Class<T> entityName, Serializable id)
			throws RuntimeException {
		return (T) this.getHibernateTemplate().load(entityName, id) ;
	}

	@Override
	public void saveEntityBaseDao(T entity) throws RuntimeException {
		this.getHibernateTemplate().save(entity) ;
		this.log.debug("[....Log4j]：持久化对象....") ;
	}

	@Override
	public Serializable saveEntityRetBaseDao(T entity) throws RuntimeException {
		return this.getHibernateTemplate().save(entity) ;
	}

	@Override
	public void updateEntityBaseDao(T entity) throws RuntimeException {
		this.getHibernateTemplate().update(entity) ;
	}
	
	/**
	 * 获得Connection来调用存储过程
	 * @return
	 */
	@SuppressWarnings("deprecation")
	protected Connection getCoonection() {
		return this.getHibernateTemplate().getSessionFactory().openSession().connection() ;
	}
	/**
	 * 断开Connection的链接
	 * @return
	 */
	protected Connection getDisconnect() {
		return this.getHibernateTemplate().getSessionFactory().openSession().disconnect() ;
	}
	
	
	/**
	 * 设置查询条件
	 * @param whereString
	 * @return
	 */
	protected static String buildWhereString(String whereString) {
		return null != whereString && !"".equals(whereString.trim()) ? BaseQuery.WHERE + whereString : "" ; 
	}

	/**
	 * 设置排序语句
	 * @param orderby
	 * @return
	 */
	protected static String buildOrderByString(LinkedHashMap<String, String> orderby) {
		StringBuffer bufStr = null;

		if (null != orderby && orderby.size() > 0) {
			bufStr = new StringBuffer();
			bufStr.append(BaseQuery.ORDERBY) ;
			for (String key : orderby.keySet()) {
				bufStr.append("o.").append(key).append(" ").append(orderby.get(key)).append(",");
			}
			bufStr.deleteCharAt(bufStr.length() - 1);

			return bufStr.toString();
		} else {
			return "";
		}
	}
	
	/**
	 * 设置条件参数
	 * @param query
	 * @param param
	 */
	protected static void setQueryParameter(Query query,Object[] param) {
		if(null != param && param.length > 0) {
			for(int i=0; i<param.length; i++) {
				query.setParameter(i, param[i]) ;
			}
		}
	}
	
	/**
	 * 获得统计查询记录
	 * @param session 会话
	 * @param queryString 查询语句
	 * @param whereString 条件语句
	 * @param param 查询参数
	 * @return long类型
	 */
	protected static long getRecordTotal(Session session,String queryString,String whereString,Object[] param) {
		Query query = session.createQuery(getCountQueryString(queryString) + buildWhereString(whereString));
		setQueryParameter(query, param) ;
		return (Long)query.uniqueResult() ;
	}
	
	/**
	 * 拼装统计查询语句
	 * @param queryString
	 * @return
	 */
	protected static String getCountQueryString(String queryString) {
		int index = queryString.indexOf("from") ;
		if(index != -1) {
			return "select count(o) " + queryString.substring(index) ;
		}
		throw new SystemException("拼装统计查询语句出错...") ;
	}
}
